// extension part
#include "extend_lua.h"

//
// demo.get(attributes, key) -> value
//
static int lget(lua_State *lua)
{
    // check argument types
    int attributes_type = lua_type(lua, -2);
    int key_type = lua_type(lua, -1);

    if(attributes_type != LUA_TLIGHTUSERDATA)
    {
        lua_pushstring(lua, "attributes argument is wrong type");
        lua_error(lua);
    }

    if(key_type != LUA_TSTRING)
    {
        lua_pushstring(lua, "key argument is wrong type");
        lua_error(lua);
    }

    // fetch arguments from stack
    Attributes *attributes = (Attributes *)lua_touserdata(lua, -2);
    std::string key = lua_tostring(lua, -1);
    lua_pop(lua, 2);

    // perform the logic
    Attributes::iterator i = attributes->find(key);
    if(i == attributes->end())
    {
        lua_pushnil(lua);
    }
    else
    {
        lua_pushstring(lua, i->second.c_str());
    }

    // return number of results
    return 1;
}

//
// demo.set(attributes, key, value)
//
static int lset(lua_State *lua)
{
    // check argument types
    int attributes_type = lua_type(lua, -3);
    int key_type = lua_type(lua, -2);
    int value_type = lua_type(lua, -1);

    if(attributes_type != LUA_TLIGHTUSERDATA)
    {
        lua_pushstring(lua, "attributes argument is wrong type");
        lua_error(lua);
    }

    if(key_type != LUA_TSTRING)
    {
        lua_pushstring(lua, "key argument is wrong type");
        lua_error(lua);
    }

    if(value_type != LUA_TSTRING)
    {
        lua_pushstring(lua, "value argument is wrong type");
        lua_error(lua);
    }

    // fetch arguments from stack
    Attributes *attributes = (Attributes *)lua_touserdata(lua, -3);
    std::string key = lua_tostring(lua, -2);
    std::string value = lua_tostring(lua, -1);
    lua_pop(lua, 3);

    // perform the logic
    Attributes::iterator i = attributes->find(key);
    if(i == attributes->end())
    {
        attributes->insert(std::make_pair(key, value));
    }
    else
    {
        i->second = value;
    }

    // return number of results
    return 0;
}

//
// demo.remove(attributes, key)
//
static int lremove(lua_State *lua)
{
    // check argument types
    int attributes_type = lua_type(lua, -2);
    int key_type = lua_type(lua, -1);

    if(attributes_type != LUA_TLIGHTUSERDATA)
    {
        lua_pushstring(lua, "attributes argument is wrong type");
        lua_error(lua);
    }

    if(key_type != LUA_TSTRING)
    {
        lua_pushstring(lua, "key argument is wrong type");
        lua_error(lua);
    }

    // fetch arguments from stack
    Attributes *attributes = (Attributes *)lua_touserdata(lua, -2);
    std::string key = lua_tostring(lua, -1);
    lua_pop(lua, 2);

    // perform the logic
    attributes->erase(key);

    // return number of results
    return 0;
}

static const struct luaL_Reg luademo [] =
{
    {"get", lget},
    {"set", lset},
    {"remove", lremove},
    {NULL, NULL}  /* sentinel */
};

int luaopen_luademo(lua_State *lua)
{
    luaL_newlib(lua, luademo);
    return 1;
}
